﻿using System;
using System.IO;
using Oblivion.Substructure.InformationManagement;

namespace Oblivion.Substructure
{
    public sealed class Configuration
    {
        // Variables that are initialized via the constructor.
        public readonly Boolean ALLOW_FLY;
        public readonly Boolean ALLOW_NETHER;
        public readonly Boolean ALLOW_PVP;
        public readonly Boolean ALLOW_RCON;
        public readonly Int32 DIFFICULTY;
        public readonly Boolean ENABLE_WHITELIST;
        public readonly Int32 GAME_MODE;
        public readonly Boolean GENERATE_STRUCTURES;
        public readonly Boolean HARDCORE;
        public readonly String LEVEL_NAME;
        public readonly Int32 LEVEL_SEED;
        public readonly String LEVEL_TYPE;
        public readonly Int32 MAX_BUILD_HEIGHT;
        public readonly Int32 MAX_PLAYERS;
        public readonly String MOTD;
        public readonly Boolean ONLINE_MODE;
        public readonly Int32 PORT;

        public readonly Int32 PROTOCOL_VERSION = 51;
        public readonly String SERVER_IP;
        public readonly Boolean SPAWN_ANIMALS;
        public readonly Boolean SPAWN_MONSTERS;
        public readonly Boolean SPAWN_NPCS;
        public readonly String TARGET_CLIENT_VERSION = "1.4.7";
        public readonly Int32 VIEW_DISTANCE;

        /// <summary> Called upon creation of the Configuration class. Gets/Sets configuration variables. </summary>
        /// <param name="config_path">The file path of the server's configuration file.</param>
        public Configuration(string config_path)
        {
            try
            {
                // Try to create the configuration using the file specified and assign values to the configuration variables.
                var configFile = new XmlFile(config_path, "Configuration");

                SERVER_IP = configFile.ReadString("Server", "IP");
                PORT = configFile.ReadInt32("Server", "Port");
                MAX_PLAYERS = configFile.ReadInt32("Server", "MaxPlayers");
                MOTD = configFile.ReadString("Server", "MOTD");
                ALLOW_NETHER = configFile.ReadBool("Server", "AllowNether");
                LEVEL_NAME = configFile.ReadString("Server", "LevelName");
                ALLOW_FLY = configFile.ReadBool("Server", "AllowFly");
                LEVEL_TYPE = configFile.ReadString("Server", "LevelType");
                ALLOW_RCON = configFile.ReadBool("Server", "AllowRCON");
                LEVEL_SEED = configFile.ReadInt32("Server", "LevelSeed");
                MAX_BUILD_HEIGHT = configFile.ReadInt32("Server", "MaxBuildHeight");
                SPAWN_NPCS = configFile.ReadBool("Server", "SpawnNPCS");
                ENABLE_WHITELIST = configFile.ReadBool("Server", "EnableWhitelist");
                SPAWN_ANIMALS = configFile.ReadBool("Server", "SpawnAnimals");
                HARDCORE = configFile.ReadBool("Server", "Hardcore");
                ONLINE_MODE = configFile.ReadBool("Server", "OnlineMode");
                ALLOW_PVP = configFile.ReadBool("Server", "PVP");
                DIFFICULTY = configFile.ReadInt32("Server", "Difficulty");
                GAME_MODE = configFile.ReadInt32("Server", "GameMode");
                SPAWN_MONSTERS = configFile.ReadBool("Server", "SpawnMonsters");
                VIEW_DISTANCE = configFile.ReadInt32("Server", "ViewDistance");
                GENERATE_STRUCTURES = configFile.ReadBool("Server", "GenerateStructures");

                // Error check:
                if (PORT == 0)
                    throw new Exception();

                Program.WriteLine("Configuration set.", ConsoleColor.Green);
                Program.WriteLine("IP: " + SERVER_IP, ConsoleColor.Cyan);
                Program.WriteLine("Port: " + PORT, ConsoleColor.Cyan);
                Program.WriteLine("Max Players: " + MAX_PLAYERS, ConsoleColor.Cyan);
                Program.WriteLine("MOTD: " + MOTD, ConsoleColor.Cyan);
                Program.WriteLine("Nether Enabled: " + ALLOW_NETHER, ConsoleColor.Cyan);
                Program.WriteLine("Level Name: " + LEVEL_NAME, ConsoleColor.Cyan);
                Program.WriteLine("Fly Enabled: " + ALLOW_FLY, ConsoleColor.Cyan);
                Program.WriteLine("Level Type: " + LEVEL_TYPE, ConsoleColor.Cyan);
                Program.WriteLine("Allow RCON: " + ALLOW_RCON, ConsoleColor.Cyan);
                Program.WriteLine("Level Seed: " + LEVEL_SEED, ConsoleColor.Cyan);
                Program.WriteLine("Max Build Height: " + MAX_BUILD_HEIGHT, ConsoleColor.Cyan);
                Program.WriteLine("Spawn NPCS: " + SPAWN_NPCS, ConsoleColor.Cyan);
                Program.WriteLine("Whitelist Enabled: " + ENABLE_WHITELIST, ConsoleColor.Cyan);
                Program.WriteLine("Spawn Animals: " + SPAWN_ANIMALS, ConsoleColor.Cyan);
                Program.WriteLine("HardCore: " + HARDCORE, ConsoleColor.Cyan);
                Program.WriteLine("Online Mode: " + ONLINE_MODE, ConsoleColor.Cyan);
                Program.WriteLine("PVP Enabled: " + ALLOW_PVP, ConsoleColor.Cyan);
                Program.WriteLine("Difficulty: " + DIFFICULTY, ConsoleColor.Cyan);
                Program.WriteLine("GameMode: " + GAME_MODE, ConsoleColor.Cyan);
                Program.WriteLine("Spawn Monsters: " + SPAWN_MONSTERS, ConsoleColor.Cyan);
                Program.WriteLine("View Distance: " + VIEW_DISTANCE, ConsoleColor.Cyan);
                Program.WriteLine("Generate Structures: " + GENERATE_STRUCTURES, ConsoleColor.Cyan);
            }
            catch
            {
                Program.WriteLine("Invalid configuration file.", ConsoleColor.Red);
                GenerateDefaultConfig();

                Program.WriteLine("");
                Program.WriteLine("Press any key to exit program...", ConsoleColor.Magenta);

                Console.ReadKey(true);
                Environment.Exit(0);
            }
        }

        /// <summary>
        /// Generates a default XML Config file
        /// </summary>
        private void GenerateDefaultConfig()
        {
            Program.WriteLine("Generating default conffiguration file...", ConsoleColor.Cyan);

            var lines = new string[26];
            lines[0] = "<Configuration>";
            lines[1] = "\t<Server>";
            lines[2] = "\t\t<IP>127.0.0.1</IP>";
            lines[3] = "\t\t<Port>1234</Port>";
            lines[4] = "\t\t<MaxPlayers>10</MaxPlayers>";
            lines[5] = "\t\t<MOTD>Hello world!</MOTD>";
            lines[6] = "\t\t<AllowNether>true</AllowNether>";
            lines[7] = "\t\t<LevelName>world</LevelName>";
            lines[8] = "\t\t<AllowFly>true</AllowFly>";
            lines[9] = "\t\t<LevelType>DEFAULT</LevelType>";
            lines[10] = "\t\t<AllowRCON>false</AllowRCON>";
            lines[11] = "\t\t<LevelSeed>1234</LevelSeed>";
            lines[12] = "\t\t<MaxBuildHeight>256</MaxBuildHeight>";
            lines[13] = "\t\t<SpawnNPCS>true</SpawnNPCS>";
            lines[14] = "\t\t<EnableWhitelist>false</EnableWhitelist>";
            lines[15] = "\t\t<SpawnAnimals>true</SpawnAnimals>";
            lines[16] = "\t\t<Hardcore>false</Hardcore>";
            lines[17] = "\t\t<OnlineMode>false</OnlineMode>";
            lines[18] = "\t\t<PVP>true</PVP>";
            lines[19] = "\t\t<Difficulty>1</Difficulty>";
            lines[20] = "\t\t<GameMode>1</GameMode>";
            lines[21] = "\t\t<SpawnMonsters>true</SpawnMonsters>";
            lines[22] = "\t\t<ViewDistance>10</ViewDistance>";
            lines[23] = "\t\t<GenerateStructures>true</GenerateStructures>";
            lines[24] = "\t</Server>";
            lines[25] = "</Configuration>";

            try
            {
                File.WriteAllLines(Kernel.ConfigPath, lines);
                Program.WriteLine("Default config file saved, please restart", ConsoleColor.Green);
            }
            catch (Exception)
            {
                Program.WriteLine("Error! Unable to generate default config file...", ConsoleColor.Red);
            }
        }
    }
}